This is an R Markdown Notebook. When you execute code within the notebook, the results appear beneath the code.

Try executing this chunk by clicking the Run button within the chunk or by placing your cursor inside it and pressing Ctrl+Shift+Enter.

#BEGIN HERE—————-

library(data.table)
library(tidyverse)
library(lubridate)
file='/media/ad/01D6B57CFBE4DB20/1.Linux/Data/FQC/V04R-V04R-SQLData_3000_head.dat' 
#file='/media/ad/01D6B57CFBE4DB20/1.Linux/Data/FQC/V04R-V04R-SQLData_3000.dat'# 3.6 GB
#file<-'/media/ad/01D6B57CFBE4DB20/1.Linux/Data/FQC/V04R-V04R-SQLData_E_series.dat' # 2.9 GB crack session (ram?)
#file<-'/media/ad/01D6B57CFBE4DB20/1.Linux/Data/FQC/V04R-V04R-SQLData_Ric.dat' # 2.8 GB OK
data_head<-fread(file,fill=TRUE,nrows=5)
data_head
#install.packages('doParallel')
#Method 1
#library(doParallel)
#no_cores <- detectCores()
#print(no_cores)
#cl <- makeCluster(no_cores)  
#registerDoParallel(cl)  
#Method 2
#library(doParallel)
#cl <- makePSOCKcluster(5)  
#registerDoParallel(cl)  
# method 3
setDTthreads(threads = 0)
getDTthreads(verbose=TRUE) 
  omp_get_num_procs()            2
  R_DATATABLE_NUM_PROCS_PERCENT  unset (default 50)
  R_DATATABLE_NUM_THREADS        unset
  R_DATATABLE_THROTTLE           unset (default 1024)
  omp_get_thread_limit()         2147483647
  omp_get_max_threads()          2
  OMP_THREAD_LIMIT               unset
  OMP_NUM_THREADS                unset
  RestoreAfterFork               true
  data.table is using 2 threads with throttle==1024. See ?setDTthreads.
[1] 2
start.time <- Sys.time()

product_type_column='V3'
tryCatch(
  expr    = {dt1 <<- fread(file,fill=TRUE,select=c(product_type_column))},
  warning = function(w){
    cat('Warning: ', w$message, '\n\n');
    n_line <- as.numeric(gsub('Stopped early on line (\\d+)\\..*','\\1',w$message))
    if (!is.na(n_line)) {
      cat('Found ', n_line,'\n')
      dt1_part1 <- fread(file,fill=TRUE, nrows=n_line-1,select=c(product_type_column))
      dt1_part2 <- fread(file,fill=TRUE,skip=n_line,select=c(product_type_column))
      dt1 <<- rbind(dt1_part1, dt1_part2, fill=T)
    }
  },
  finally = cat("\nFinished. \n")
  #finally=.Call(CfreadCleanup)
);

Finished. 
end.time <- Sys.time()
time.taken <- end.time - start.time
time.taken 
Time difference of 0.2093291 secs
# No Parallel: 1.118 mins
# doParallel method 1: 1.097 mins --> run lan 2 la 58 or 52 s 
# doParallel method 2: 1.118 mins
# doParallel method 3: 51 s
#install.packages("pryr")
library(pryr)
Registered S3 method overwritten by 'pryr':
  method      from
  print.bytes Rcpp

Attaching package: ‘pryr’

The following objects are masked from ‘package:purrr’:

    compose, partial

The following object is masked from ‘package:data.table’:

    address
object_size(dt1) # 43.7 MB
405 kB
#product_type_column='V3'
#dt1<-fread(file,fill=TRUE,select=c(product_type_column))
dim(dt1)
[1] 50000     1
head(dt1)
tail(dt1)
class(dt1)
[1] "data.table" "data.frame"
product_all <- as.data.frame(table(dt1)) %>% 
  arrange(desc(Freq)) %>% 
  top_n(20,Freq)
product_all
product_all %>% 
  ggplot(aes(x= reorder(dt1, -Freq),y=Freq)) +
  geom_bar(stat="identity",fill="steelblue")+
  theme(axis.text.x=element_text(angle=90))

# Please choose product_type:
product_type='31AA015'
#product_type='31A007G_P'
# Please choose parameter column to show
parameter_column_name='V65'
parameter_column_value='V66'
# Default time column:
product_type_column='V3'
date_column='V6'
start.time <- Sys.time()
tryCatch(
  expr    = {dt2 <<- fread(file,fill=TRUE,select=c(product_type_column,date_column,parameter_column_name,parameter_column_value)) %>% 
    filter(V3 ==product_type)
  },
  warning = function(w){
    cat('Warning: ', w$message, '\n\n');
    n_line2 <- as.numeric(gsub('Stopped early on line (\\d+)\\..*','\\1',w$message))
    if (!is.na(n_line2)) {
      cat('Found ', n_line2,'\n')
      dt2_part1 <- fread(file,fill=TRUE, nrows=n_line2-1,select=c(product_type_column,date_column,parameter_column_name,parameter_column_value))
      dt2_part2 <- fread(file,fill=TRUE,skip=n_line2,select=c(product_type_column,date_column,
                                                          parameter_column_name,parameter_column_value))
      dt2 <<- rbind(dt2_part1, dt2_part2, fill=T)%>% 
      filter(V3 ==product_type)
    }
  },
  finally = cat("\nFinished. \n")
);

Finished. 
end.time <- Sys.time()
time.taken <- end.time - start.time
time.taken # 1.1207 mins , run lan 2: 46.15 s
Time difference of 0.1885769 secs
# Method 3: 43 s
object_size(dt2) # 60 MB
754 kB
env <- environment()
all_data_memory <-data.frame(
object = ls(env),
size = unlist(lapply(
  ls(env), function(x) {
  object.size(get(x, envir = env, inherits = FALSE))
}
)))
all_data_memory
#60 Megabytes (MB)  =   62,914,560 Bytes (B)
#Remove dt 1 to save ram
#rm(dt1)
dim(dt2)
[1] 6965    4
head(dt2)
tail(dt2)
colnames(dt2) <- c("product_type", "date","parameter_name","parameter_value")
dt2
print(dim(dt2))
[1] 6965    4
sl<-object.size(dt2)
print(sl, units = "auto", standard = "SI") 
754 kB
data_process <- dt2 %>%
  mutate( date_trans=mdy_hms(date), # must have mdy_hms for convert date time
          date_filter=as_date(date_trans),
         )
head(data_process)
tail(data_process)
print(dim(data_process))
[1] 6965    6
sl<-object.size(data_process)
print(sl, units = "auto", standard = "SI") 
866.5 kB
#rm(dt2)
min(data_process$date)
[1] "12/18/2017 23:31:1"
max(data_process$date)
[1] "12/27/2017 23:30:1"
data_process[which.max(data_process$date)]
NAs introduced by coercion
class(data_process$date_trans)
[1] "POSIXct" "POSIXt" 
class(data_process$date)
[1] "character"
min(data_process$date_trans)
[1] "2017-12-18 23:31:01 UTC"
max(data_process$date_trans)
[1] "2017-12-27 23:30:01 UTC"
dim(data_process)
[1] 6965    6
#data_process %>% 
#  filter(date_trans>=as.POSIXct("2017-12-20 23:30:01",tz="UTC"))
#please choose specific time to show
#year_select=2017
#month_select=12
#day_select=22
#df_plot <- data_process %>% 
#  select(date_trans,date,parameter_name,parameter_value,year,month,day) %>% 
#  filter(year==year_select,month==month_select,day==day_select)
#df_plot
# Best to choose
date_choose="2017-12-19"
df_plot2 <- data_process %>% 
  select(date_trans,date,date_filter,parameter_name,parameter_value) %>% 
  filter(date_filter==ymd(date_choose))
df_plot2
summary(df_plot2)
   date_trans                      date            date_filter         parameter_name
 Min.   :2017-12-19 00:00:03   Length:1136        Min.   :2017-12-19   Min.   :500   
 1st Qu.:2017-12-19 00:38:14   Class :character   1st Qu.:2017-12-19   1st Qu.:500   
 Median :2017-12-19 01:15:41   Mode  :character   Median :2017-12-19   Median :500   
 Mean   :2017-12-19 08:22:41                      Mean   :2017-12-19   Mean   :500   
 3rd Qu.:2017-12-19 22:50:21                      3rd Qu.:2017-12-19   3rd Qu.:500   
 Max.   :2017-12-19 23:35:56                      Max.   :2017-12-19   Max.   :500   
 parameter_value
 Min.   :104.0  
 1st Qu.:106.9  
 Median :107.0  
 Mean   :107.0  
 3rd Qu.:107.1  
 Max.   :107.5  
#install.packages('pastecs')
library(pastecs)

Attaching package: ‘pastecs’

The following objects are masked from ‘package:xts’:

    first, last

The following objects are masked from ‘package:dplyr’:

    first, last

The following object is masked from ‘package:tidyr’:

    extract

The following objects are masked from ‘package:data.table’:

    first, last
stat.desc(df_plot2 %>% select(parameter_name,parameter_value))
#install.packages('Hmisc')
library(Hmisc)
Loading required package: lattice
Loading required package: survival
Loading required package: Formula

Attaching package: ‘Hmisc’

The following object is masked from ‘package:psych’:

    describe

The following object is masked from ‘package:plotly’:

    subplot

The following objects are masked from ‘package:dplyr’:

    src, summarize

The following objects are masked from ‘package:base’:

    format.pval, units
describe(df_plot2 %>% select(parameter_name,parameter_value))
df_plot2 %>% select(parameter_name, parameter_value) 

 2  Variables      1136  Observations
----------------------------------------------------------------------------------------
parameter_name 
       n  missing distinct     Info     Mean      Gmd 
    1136        0        1        0      500        0 
               
Value       500
Frequency  1136
Proportion    1
----------------------------------------------------------------------------------------
parameter_value 
       n  missing distinct     Info     Mean      Gmd      .05      .10      .25 
    1136        0      588        1      107   0.2346    106.6    106.7    106.9 
     .50      .75      .90      .95 
   107.0    107.1    107.2    107.3 

lowest : 104.018 104.333 105.644 105.825 106.103, highest: 107.438 107.442 107.453 107.466 107.511
----------------------------------------------------------------------------------------
#install.packages('psych')
library(psych)
describe(df_plot2 %>% select(parameter_name,parameter_value))
df_plot2 %>% select(parameter_name, parameter_value) 

 2  Variables      1136  Observations
----------------------------------------------------------------------------------------
parameter_name 
       n  missing distinct     Info     Mean      Gmd 
    1136        0        1        0      500        0 
               
Value       500
Frequency  1136
Proportion    1
----------------------------------------------------------------------------------------
parameter_value 
       n  missing distinct     Info     Mean      Gmd      .05      .10      .25 
    1136        0      588        1      107   0.2346    106.6    106.7    106.9 
     .50      .75      .90      .95 
   107.0    107.1    107.2    107.3 

lowest : 104.018 104.333 105.644 105.825 106.103, highest: 107.438 107.442 107.453 107.466 107.511
----------------------------------------------------------------------------------------
df_plot2 %>% select(parameter_value) %>% 
  ggplot(aes(y=parameter_value))+
  geom_histogram()

# library(plotly)
# ay <- list(
#   tickfont = list(color = "red"),
#   overlaying = "y",
#   side = "right",
#   title = "second y axis"
# )
# p <- df_plot2 %>% 
#       #arrange(date_trans) %>% 
#       plot_ly(x =~date_trans, y = ~parameter_value,name='value',
#               type='scatter',mode='lines+markers')%>% 
#               add_trace(x=~date_trans, y = ~parameter_name,name='name',
#               type='scatter',mode='lines',yaxis='y2') %>% 
#               layout(yaxis2 = list(overlaying = "y", side = "right")
#               )
# p
#p1<-plot_ly(df_plot2,x =~date_trans, y = ~parameter_value) %>% 
#  add_lines(name='Value') %>% 
#p2<-plot_ly(df_plot2,x =~date_trans, y = ~parameter_name) %>% 
#  add_lines(name='Frequency')
#subplot(p1, p2,nrows=2,shareX = TRUE)
library(plotly)
p1<-plot_ly(df_plot2,x =~date_trans, y = ~parameter_value) %>% 
  add_trace(mode='lines+markers',name='Value')
p2<-plot_ly(df_plot2,x =~date_trans, y = ~parameter_name) %>% 
  add_trace(mode='lines+markers',name='Frequency')

plotly::subplot(p1, p2,nrows=2,shareX = TRUE)
No trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plot.ly/r/reference/#scatter
No trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plot.ly/r/reference/#scatter
select_data<-df_plot2$parameter_value
Q1 <- quantile(select_data, .25)
Q3 <- quantile(select_data, .75)
IQR <- IQR(select_data)
k=3
df_plot_no_outlier <- subset(df_plot2, select_data> (Q1 - k*IQR) & select_data< (Q3 + k*IQR))

print(dim(df_plot2))
[1] 1136    5
print(dim(df_plot_no_outlier))
[1] 1132    5
p1<-plot_ly(df_plot_no_outlier,x =~date_trans, y = ~parameter_value) %>% 
  add_trace(mode='lines+markers',name='Value')
p2<-plot_ly(df_plot_no_outlier,x =~date_trans, y = ~parameter_name) %>% 
  add_trace(mode='lines+markers',name='Frequency')
p<-plotly::subplot(p1, p2,nrows=2,shareX = TRUE)
No trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plot.ly/r/reference/#scatter
No trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plot.ly/r/reference/#scatter
p
p1<-plot_ly(df_plot_no_outlier,x =~date_trans, y = ~parameter_value) %>% 
  add_trace(mode='lines+markers',name='Value')
#p2<-plot_ly(df_plot_no_outlier,x =~date_trans, y = ~parameter_name) %>% 
#  add_trace(mode='lines+markers',name='Frequency')
#p<-subplot(p1, p2,nrows=2,shareX = TRUE)
p1
No trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plot.ly/r/reference/#scatter
No trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plot.ly/r/reference/#scatter
p1<-plot_ly(df_plot_no_outlier,x =~date_trans, y = ~parameter_value) %>% 
  add_trace(mode='lines+markers',name='Value') %>% 
  layout(
    title = "FQC data daily",
    xaxis = list(
      rangeselector = list(
        buttons = list(
          list(
            count = 30,
            label = "min",
            step = "minute",
            stepmode = "backward"),
          list(
            count = 2,
            label = "hour",
            step = "hour",
            stepmode = "backward"),
          list(step = "all"))),

      rangeslider = list(type = "date")),

    yaxis = list(title = "Value"))
p1
No trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plot.ly/r/reference/#scatter
No trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plot.ly/r/reference/#scatter
# ay <- list(
#   tickfont = list(color = "red"),
#   overlaying = "y",
#   side = "right",
#   title = "second y axis"
# )
# p <- df_plot_no_outlier %>% 
#       arrange(date_trans) %>% 
#       plot_ly(x =~date_trans, y = ~parameter_value,name='value',
#               type='scatter',mode='lines+markers')%>% 
#               add_trace(x=~date_trans, y = ~parameter_name,name='name',
#               type='scatter',mode='lines',yaxis='y2') %>% 
#               layout(yaxis2 = list(overlaying = "y", side = "right")
#               )
# p
num_points=dim(df_plot_no_outlier)[1]
num_points
[1] 1132
USL_value=''
LSL_value=''
LSL<-rep(LSL_value,num_points)
USL<-rep(USL_value,num_points)
p1%>% 
  add_trace(y = ~USL, name = 'USL', mode = 'lines',color="rgba(255, 0, 0, 0.6)") %>% 
  add_trace(y = ~LSL, name = 'LSL', mode = 'lines',color="rgb(20, 20, 20)")
No trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plot.ly/r/reference/#scatter
No trace type specified:
  Based on info supplied, a 'bar' trace seems appropriate.
  Read more about this trace type -> https://plot.ly/r/reference/#bar
No trace type specified:
  Based on info supplied, a 'bar' trace seems appropriate.
  Read more about this trace type -> https://plot.ly/r/reference/#bar
minimal value for n is 3, returning requested palette with 3 different levels
minimal value for n is 3, returning requested palette with 3 different levels
Can't display both discrete & non-discrete data on same axis'bar' objects don't have these attributes: 'mode'
Valid attributes include:
'type', 'visible', 'showlegend', 'legendgroup', 'opacity', 'name', 'uid', 'ids', 'customdata', 'meta', 'selectedpoints', 'hoverinfo', 'hoverlabel', 'stream', 'transforms', 'uirevision', 'x', 'x0', 'dx', 'y', 'y0', 'dy', 'text', 'texttemplate', 'hovertext', 'hovertemplate', 'textposition', 'insidetextanchor', 'textangle', 'textfont', 'insidetextfont', 'outsidetextfont', 'constraintext', 'cliponaxis', 'orientation', 'base', 'offset', 'width', 'marker', 'offsetgroup', 'alignmentgroup', 'selected', 'unselected', 'r', 't', '_deprecated', 'error_x', 'error_y', 'xcalendar', 'ycalendar', 'xaxis', 'yaxis', 'idssrc', 'customdatasrc', 'metasrc', 'hoverinfosrc', 'xsrc', 'ysrc', 'textsrc', 'texttemplatesrc', 'hovertextsrc', 'hovertemplatesrc', 'textpositionsrc', 'basesrc', 'offsetsrc', 'widthsrc', 'rsrc', 'tsrc', 'key', 'set', 'frame', 'transforms', '_isNestedKey', '_isSimpleKey', '_isGraticule', '_bbox'
'bar' objects don't have these attributes: 'mode'
Valid attributes include:
'type', 'visible', 'showlegend', 'legendgroup', 'opacity', 'name', 'uid', 'ids', 'customdata', 'meta', 'selectedpoints', 'hoverinfo', 'hoverlabel', 'stream', 'transforms', 'uirevision', 'x', 'x0', 'dx', 'y', 'y0', 'dy', 'text', 'texttemplate', 'hovertext', 'hovertemplate', 'textposition', 'insidetextanchor', 'textangle', 'textfont', 'insidetextfont', 'outsidetextfont', 'constraintext', 'cliponaxis', 'orientation', 'base', 'offset', 'width', 'marker', 'offsetgroup', 'alignmentgroup', 'selected', 'unselected', 'r', 't', '_deprecated', 'error_x', 'error_y', 'xcalendar', 'ycalendar', 'xaxis', 'yaxis', 'idssrc', 'customdatasrc', 'metasrc', 'hoverinfosrc', 'xsrc', 'ysrc', 'textsrc', 'texttemplatesrc', 'hovertextsrc', 'hovertemplatesrc', 'textpositionsrc', 'basesrc', 'offsetsrc', 'widthsrc', 'rsrc', 'tsrc', 'key', 'set', 'frame', 'transforms', '_isNestedKey', '_isSimpleKey', '_isGraticule', '_bbox'
No trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plot.ly/r/reference/#scatter
No trace type specified:
  Based on info supplied, a 'bar' trace seems appropriate.
  Read more about this trace type -> https://plot.ly/r/reference/#bar
No trace type specified:
  Based on info supplied, a 'bar' trace seems appropriate.
  Read more about this trace type -> https://plot.ly/r/reference/#bar
minimal value for n is 3, returning requested palette with 3 different levels
minimal value for n is 3, returning requested palette with 3 different levels
Can't display both discrete & non-discrete data on same axis'bar' objects don't have these attributes: 'mode'
Valid attributes include:
'type', 'visible', 'showlegend', 'legendgroup', 'opacity', 'name', 'uid', 'ids', 'customdata', 'meta', 'selectedpoints', 'hoverinfo', 'hoverlabel', 'stream', 'transforms', 'uirevision', 'x', 'x0', 'dx', 'y', 'y0', 'dy', 'text', 'texttemplate', 'hovertext', 'hovertemplate', 'textposition', 'insidetextanchor', 'textangle', 'textfont', 'insidetextfont', 'outsidetextfont', 'constraintext', 'cliponaxis', 'orientation', 'base', 'offset', 'width', 'marker', 'offsetgroup', 'alignmentgroup', 'selected', 'unselected', 'r', 't', '_deprecated', 'error_x', 'error_y', 'xcalendar', 'ycalendar', 'xaxis', 'yaxis', 'idssrc', 'customdatasrc', 'metasrc', 'hoverinfosrc', 'xsrc', 'ysrc', 'textsrc', 'texttemplatesrc', 'hovertextsrc', 'hovertemplatesrc', 'textpositionsrc', 'basesrc', 'offsetsrc', 'widthsrc', 'rsrc', 'tsrc', 'key', 'set', 'frame', 'transforms', '_isNestedKey', '_isSimpleKey', '_isGraticule', '_bbox'
'bar' objects don't have these attributes: 'mode'
Valid attributes include:
'type', 'visible', 'showlegend', 'legendgroup', 'opacity', 'name', 'uid', 'ids', 'customdata', 'meta', 'selectedpoints', 'hoverinfo', 'hoverlabel', 'stream', 'transforms', 'uirevision', 'x', 'x0', 'dx', 'y', 'y0', 'dy', 'text', 'texttemplate', 'hovertext', 'hovertemplate', 'textposition', 'insidetextanchor', 'textangle', 'textfont', 'insidetextfont', 'outsidetextfont', 'constraintext', 'cliponaxis', 'orientation', 'base', 'offset', 'width', 'marker', 'offsetgroup', 'alignmentgroup', 'selected', 'unselected', 'r', 't', '_deprecated', 'error_x', 'error_y', 'xcalendar', 'ycalendar', 'xaxis', 'yaxis', 'idssrc', 'customdatasrc', 'metasrc', 'hoverinfosrc', 'xsrc', 'ysrc', 'textsrc', 'texttemplatesrc', 'hovertextsrc', 'hovertemplatesrc', 'textpositionsrc', 'basesrc', 'offsetsrc', 'widthsrc', 'rsrc', 'tsrc', 'key', 'set', 'frame', 'transforms', '_isNestedKey', '_isSimpleKey', '_isGraticule', '_bbox'

Try another chart: High chart

head(df_plot_no_outlier)

TRY OTHER METHOD:

#install.packages('highcharter')
library(highcharter)
Registered S3 method overwritten by 'quantmod':
  method            from
  as.zoo.data.frame zoo 
dt2%>%
  hchart(type = "line", hcaes(x = V6, y = V66))
Error: Problem with `mutate()` input `x`.
x object 'V6' not found
ℹ Input `x` is `V6`.
Run `rlang::last_error()` to see where the error occurred.
df_plot_no_outlier%>%
  hchart(type = "line", hcaes(x = as.character(date_trans), y = parameter_value))
#install.packages("dygraphs")
library(dygraphs)
df_plot_no_outlier
dt2
Sys.timezone()
[1] "Asia/Ho_Chi_Minh"
tzone(data_time$date_trans)
[1] "UTC"
tzone(df_plot_no_outlier$date_trans)
[1] "UTC"
# Switch to XTS format
data <- xts(x = dt2$V66, 
            order.by = mdy_hms(dt2$V6))
# Add points
p <- dygraph(data) %>%
  dyOptions( drawPoints = TRUE, pointSize = 4,useDataTimezone = TRUE )%>% 
  dyRangeSelector()
p
# Switch to XTS format
data <- xts(x = df_plot_no_outlier$parameter_value, 
            order.by = df_plot_no_outlier$date_trans)
# Add points
p <- dygraph(data) %>%
  dyOptions( drawPoints = TRUE, pointSize = 4,useDataTimezone = TRUE )%>% 
  dyRangeSelector()
p
df_plot_no_outlier
dygraph(df_plot_no_outlier %>% select(date_trans,parameter_value), main = "All", group = "lung-deaths")%>%
  dyOptions( drawPoints = TRUE, pointSize = 4,useDataTimezone = TRUE )

dygraph(df_plot_no_outlier %>% select(date_trans,parameter_name), main = "All", group = "lung-deaths")%>%
  dyOptions( drawPoints = TRUE, pointSize = 4,useDataTimezone = TRUE )
dy_graph <- list(
  dygraph(df_plot_no_outlier %>% select(date_trans,parameter_value), main = "temperature", group = "lung-deaths")%>%
  dyOptions( drawPoints = TRUE, pointSize = 4,useDataTimezone = TRUE ),
dygraph(df_plot_no_outlier %>% select(date_trans,parameter_name), main = "rainfall", group = "lung-deaths")%>%
  dyOptions( drawPoints = TRUE, pointSize = 4,useDataTimezone = TRUE )
)  # end list

# render the dygraphs objects using htmltools
htmltools::browsable(htmltools::tagList(dy_graph))
# Please choose product_type:
file='/media/ad/01D6B57CFBE4DB20/1.Linux/Data/FQC/V04R-V04R-SQLData_3000_head.dat' 
#product_type='31AA015'
product_type_choose='31AA015'
#product_type='31A007G_P'
# Please choose parameter column to show
parameter_column_name='V65'
parameter_column_value='V66'
# Default time column:
product_type_column='V3'
date_column='V6'

savefunc2 <- function(file_path,product_type_column,product_type_choose=NULL,date_column=NULL,
                        parameter_column_name=NULL,parameter_column_value=NULL){
    tryCatch(
      expr    = {
        if ( is.null(product_type_choose)){
          print('not filter')
          dt2 <<- fread(file_path,fill=TRUE,select=c(product_type_column,date_column,parameter_column_name,parameter_column_value))}
        else{
          print('filter')
          dt2 <<- fread(file_path,fill=TRUE,select=c(product_type_column,date_column,parameter_column_name,parameter_column_value)) %>%
          filter(V3 ==product_type_choose)}
        
      },
      warning = function(w){
        cat('Warning: ', w$message, '\n\n');
        n_line2 <- as.numeric(gsub('Stopped early on line (\\d+)\\..*','\\1',w$message))
        if (!is.na(n_line2)) {
          cat('Found ', n_line2,'\n')
          dt2_part1 <- fread(file_path,fill=TRUE, nrows=n_line2-1,select=c(product_type_column,date_column,parameter_column_name,parameter_column_value))
          dt2_part2 <- fread(file_path,fill=TRUE,skip=n_line2,select=c(product_type_column,date_column,parameter_column_name,parameter_column_value))
          if ( is.null(product_type_choose)){
            dt2 <<- rbind(dt2_part1, dt2_part2, fill=T)
          }else{
            dt2 <<- rbind(dt2_part1, dt2_part2, fill=T)%>%
              filter(V3 ==product_type_choose)  
          }
          
        }
      },
      finally = cat("\nFinished. \n")
    );
}


dt<-savefunc2(file,product_type_column,product_type_choose,date_column,parameter_column_name,parameter_column_value)
colnames(dt) <- c("product_type", "date","parameter_freq","parameter_value")
dt<-dt %>%
  mutate( date_trans=mdy_hms(date), # must have mdy_hms for convert date time
          date_filter=as_date(date_trans),
          )
dt
dt<-savefunc2(file,product_type_column)
dt
plotly_chart <- function(data_one_date,check_input_remove_frequency_chart,
                         check_go_data_analyze_date){
  req(check_go_data_analyze_date)
  p1<-plot_ly(data_one_date,x =~date_trans, y = ~parameter_value) %>%
      add_trace(mode='lines+markers',name='Value')
    if (check_input_remove_frequency_chart){
      p1
    } else {
      p2<-plot_ly(data_one_date,x =~date_trans, y = ~parameter_freq) %>%
        add_trace(mode='lines+markers',name='Frequency')
      plotly::subplot(p1, p2,nrows=2,shareX = TRUE)
      
    }
}
plotly_chart(data_one_date(),input$remove_frequency_chart,input$go_data_analyze_date)
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKVGhpcyBpcyBhbiBbUiBNYXJrZG93bl0oaHR0cDovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbSkgTm90ZWJvb2suIFdoZW4geW91IGV4ZWN1dGUgY29kZSB3aXRoaW4gdGhlIG5vdGVib29rLCB0aGUgcmVzdWx0cyBhcHBlYXIgYmVuZWF0aCB0aGUgY29kZS4gCgpUcnkgZXhlY3V0aW5nIHRoaXMgY2h1bmsgYnkgY2xpY2tpbmcgdGhlICpSdW4qIGJ1dHRvbiB3aXRoaW4gdGhlIGNodW5rIG9yIGJ5IHBsYWNpbmcgeW91ciBjdXJzb3IgaW5zaWRlIGl0IGFuZCBwcmVzc2luZyAqQ3RybCtTaGlmdCtFbnRlciouIAoKI0JFR0lOIEhFUkUtLS0tLS0tLS0tLS0tLS0tCgpgYGB7cn0KbGlicmFyeShkYXRhLnRhYmxlKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShsdWJyaWRhdGUpCmBgYAoKYGBge3J9CmZpbGU9Jy9tZWRpYS9hZC8wMUQ2QjU3Q0ZCRTREQjIwLzEuTGludXgvRGF0YS9GUUMvVjA0Ui1WMDRSLVNRTERhdGFfMzAwMF9oZWFkLmRhdCcgCiNmaWxlPScvbWVkaWEvYWQvMDFENkI1N0NGQkU0REIyMC8xLkxpbnV4L0RhdGEvRlFDL1YwNFItVjA0Ui1TUUxEYXRhXzMwMDAuZGF0JyMgMy42IEdCCiNmaWxlPC0nL21lZGlhL2FkLzAxRDZCNTdDRkJFNERCMjAvMS5MaW51eC9EYXRhL0ZRQy9WMDRSLVYwNFItU1FMRGF0YV9FX3Nlcmllcy5kYXQnICMgMi45IEdCIGNyYWNrIHNlc3Npb24gKHJhbT8pCiNmaWxlPC0nL21lZGlhL2FkLzAxRDZCNTdDRkJFNERCMjAvMS5MaW51eC9EYXRhL0ZRQy9WMDRSLVYwNFItU1FMRGF0YV9SaWMuZGF0JyAjIDIuOCBHQiBPSwpkYXRhX2hlYWQ8LWZyZWFkKGZpbGUsZmlsbD1UUlVFLG5yb3dzPTUpCmRhdGFfaGVhZApgYGAKYGBge3J9CiNpbnN0YWxsLnBhY2thZ2VzKCdkb1BhcmFsbGVsJykKI01ldGhvZCAxCiNsaWJyYXJ5KGRvUGFyYWxsZWwpCiNub19jb3JlcyA8LSBkZXRlY3RDb3JlcygpCiNwcmludChub19jb3JlcykKI2NsIDwtIG1ha2VDbHVzdGVyKG5vX2NvcmVzKSAgCiNyZWdpc3RlckRvUGFyYWxsZWwoY2wpICAKCmBgYApgYGB7cn0KI01ldGhvZCAyCiNsaWJyYXJ5KGRvUGFyYWxsZWwpCiNjbCA8LSBtYWtlUFNPQ0tjbHVzdGVyKDUpICAKI3JlZ2lzdGVyRG9QYXJhbGxlbChjbCkgIApgYGAKCmBgYHtyfQojIG1ldGhvZCAzCnNldERUdGhyZWFkcyh0aHJlYWRzID0gMCkKZ2V0RFR0aHJlYWRzKHZlcmJvc2U9VFJVRSkgCmBgYAoKYGBge3J9CnN0YXJ0LnRpbWUgPC0gU3lzLnRpbWUoKQoKcHJvZHVjdF90eXBlX2NvbHVtbj0nVjMnCnRyeUNhdGNoKAogIGV4cHIgICAgPSB7ZHQxIDw8LSBmcmVhZChmaWxlLGZpbGw9VFJVRSxzZWxlY3Q9Yyhwcm9kdWN0X3R5cGVfY29sdW1uKSl9LAogIHdhcm5pbmcgPSBmdW5jdGlvbih3KXsKICAgIGNhdCgnV2FybmluZzogJywgdyRtZXNzYWdlLCAnXG5cbicpOwogICAgbl9saW5lIDwtIGFzLm51bWVyaWMoZ3N1YignU3RvcHBlZCBlYXJseSBvbiBsaW5lIChcXGQrKVxcLi4qJywnXFwxJyx3JG1lc3NhZ2UpKQogICAgaWYgKCFpcy5uYShuX2xpbmUpKSB7CiAgICAgIGNhdCgnRm91bmQgJywgbl9saW5lLCdcbicpCiAgICAgIGR0MV9wYXJ0MSA8LSBmcmVhZChmaWxlLGZpbGw9VFJVRSwgbnJvd3M9bl9saW5lLTEsc2VsZWN0PWMocHJvZHVjdF90eXBlX2NvbHVtbikpCiAgICAgIGR0MV9wYXJ0MiA8LSBmcmVhZChmaWxlLGZpbGw9VFJVRSxza2lwPW5fbGluZSxzZWxlY3Q9Yyhwcm9kdWN0X3R5cGVfY29sdW1uKSkKICAgICAgZHQxIDw8LSByYmluZChkdDFfcGFydDEsIGR0MV9wYXJ0MiwgZmlsbD1UKQogICAgfQogIH0sCiAgZmluYWxseSA9IGNhdCgiXG5GaW5pc2hlZC4gXG4iKQogICNmaW5hbGx5PS5DYWxsKENmcmVhZENsZWFudXApCik7CmVuZC50aW1lIDwtIFN5cy50aW1lKCkKdGltZS50YWtlbiA8LSBlbmQudGltZSAtIHN0YXJ0LnRpbWUKdGltZS50YWtlbiAKIyBObyBQYXJhbGxlbDogMS4xMTggbWlucwojIGRvUGFyYWxsZWwgbWV0aG9kIDE6IDEuMDk3IG1pbnMgLS0+IHJ1biBsYW4gMiBsYSA1OCBvciA1MiBzIAojIGRvUGFyYWxsZWwgbWV0aG9kIDI6IDEuMTE4IG1pbnMKIyBkb1BhcmFsbGVsIG1ldGhvZCAzOiA1MSBzCmBgYApgYGB7cn0KI2luc3RhbGwucGFja2FnZXMoInByeXIiKQpsaWJyYXJ5KHByeXIpCm9iamVjdF9zaXplKGR0MSkgIyA0My43IE1CCmBgYAoKCmBgYHtyfQojcHJvZHVjdF90eXBlX2NvbHVtbj0nVjMnCiNkdDE8LWZyZWFkKGZpbGUsZmlsbD1UUlVFLHNlbGVjdD1jKHByb2R1Y3RfdHlwZV9jb2x1bW4pKQpkaW0oZHQxKQpoZWFkKGR0MSkKdGFpbChkdDEpCmBgYApgYGB7cn0KY2xhc3MoZHQxKQpgYGAKCgpgYGB7cn0KcHJvZHVjdF9hbGwgPC0gYXMuZGF0YS5mcmFtZSh0YWJsZShkdDEpKSAlPiUgCiAgYXJyYW5nZShkZXNjKEZyZXEpKSAlPiUgCiAgdG9wX24oMjAsRnJlcSkKcHJvZHVjdF9hbGwKYGBgCmBgYHtyfQpwcm9kdWN0X2FsbCAlPiUgCiAgZ2dwbG90KGFlcyh4PSByZW9yZGVyKGR0MSwgLUZyZXEpLHk9RnJlcSkpICsKICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIsZmlsbD0ic3RlZWxibHVlIikrCiAgdGhlbWUoYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KGFuZ2xlPTkwKSkKYGBgCgpgYGB7cn0KIyBQbGVhc2UgY2hvb3NlIHByb2R1Y3RfdHlwZToKcHJvZHVjdF90eXBlPSczMUFBMDE1JwojcHJvZHVjdF90eXBlPSczMUEwMDdHX1AnCiMgUGxlYXNlIGNob29zZSBwYXJhbWV0ZXIgY29sdW1uIHRvIHNob3cKcGFyYW1ldGVyX2NvbHVtbl9uYW1lPSdWNjUnCnBhcmFtZXRlcl9jb2x1bW5fdmFsdWU9J1Y2NicKIyBEZWZhdWx0IHRpbWUgY29sdW1uOgpwcm9kdWN0X3R5cGVfY29sdW1uPSdWMycKZGF0ZV9jb2x1bW49J1Y2JwpgYGAKCmBgYHtyfQpzdGFydC50aW1lIDwtIFN5cy50aW1lKCkKdHJ5Q2F0Y2goCiAgZXhwciAgICA9IHtkdDIgPDwtIGZyZWFkKGZpbGUsZmlsbD1UUlVFLHNlbGVjdD1jKHByb2R1Y3RfdHlwZV9jb2x1bW4sZGF0ZV9jb2x1bW4scGFyYW1ldGVyX2NvbHVtbl9uYW1lLHBhcmFtZXRlcl9jb2x1bW5fdmFsdWUpKSAlPiUgCiAgICBmaWx0ZXIoVjMgPT1wcm9kdWN0X3R5cGUpCiAgfSwKICB3YXJuaW5nID0gZnVuY3Rpb24odyl7CiAgICBjYXQoJ1dhcm5pbmc6ICcsIHckbWVzc2FnZSwgJ1xuXG4nKTsKICAgIG5fbGluZTIgPC0gYXMubnVtZXJpYyhnc3ViKCdTdG9wcGVkIGVhcmx5IG9uIGxpbmUgKFxcZCspXFwuLionLCdcXDEnLHckbWVzc2FnZSkpCiAgICBpZiAoIWlzLm5hKG5fbGluZTIpKSB7CiAgICAgIGNhdCgnRm91bmQgJywgbl9saW5lMiwnXG4nKQogICAgICBkdDJfcGFydDEgPC0gZnJlYWQoZmlsZSxmaWxsPVRSVUUsIG5yb3dzPW5fbGluZTItMSxzZWxlY3Q9Yyhwcm9kdWN0X3R5cGVfY29sdW1uLGRhdGVfY29sdW1uLHBhcmFtZXRlcl9jb2x1bW5fbmFtZSxwYXJhbWV0ZXJfY29sdW1uX3ZhbHVlKSkKICAgICAgZHQyX3BhcnQyIDwtIGZyZWFkKGZpbGUsZmlsbD1UUlVFLHNraXA9bl9saW5lMixzZWxlY3Q9Yyhwcm9kdWN0X3R5cGVfY29sdW1uLGRhdGVfY29sdW1uLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFyYW1ldGVyX2NvbHVtbl9uYW1lLHBhcmFtZXRlcl9jb2x1bW5fdmFsdWUpKQogICAgICBkdDIgPDwtIHJiaW5kKGR0Ml9wYXJ0MSwgZHQyX3BhcnQyLCBmaWxsPVQpJT4lIAogICAgICBmaWx0ZXIoVjMgPT1wcm9kdWN0X3R5cGUpCiAgICB9CiAgfSwKICBmaW5hbGx5ID0gY2F0KCJcbkZpbmlzaGVkLiBcbiIpCik7CmVuZC50aW1lIDwtIFN5cy50aW1lKCkKdGltZS50YWtlbiA8LSBlbmQudGltZSAtIHN0YXJ0LnRpbWUKdGltZS50YWtlbiAjIDEuMTIwNyBtaW5zICwgcnVuIGxhbiAyOiA0Ni4xNSBzCiMgTWV0aG9kIDM6IDQzIHMKYGBgCgoKYGBge3J9Cm9iamVjdF9zaXplKGR0MikgIyA2MCBNQgpgYGAKCmBgYHtyfQplbnYgPC0gZW52aXJvbm1lbnQoKQphbGxfZGF0YV9tZW1vcnkgPC1kYXRhLmZyYW1lKApvYmplY3QgPSBscyhlbnYpLApzaXplID0gdW5saXN0KGxhcHBseSgKICBscyhlbnYpLCBmdW5jdGlvbih4KSB7CiAgb2JqZWN0LnNpemUoZ2V0KHgsIGVudmlyID0gZW52LCBpbmhlcml0cyA9IEZBTFNFKSkKfQopKSkKYWxsX2RhdGFfbWVtb3J5CiM2MCBNZWdhYnl0ZXMgKE1CKQk9CTYyLDkxNCw1NjAgQnl0ZXMgKEIpCmBgYAoKYGBge3J9CiNSZW1vdmUgZHQgMSB0byBzYXZlIHJhbQojcm0oZHQxKQpgYGAKCgoKYGBge3J9CmRpbShkdDIpCmhlYWQoZHQyKQp0YWlsKGR0MikKYGBgCgoKYGBge3J9CmNvbG5hbWVzKGR0MikgPC0gYygicHJvZHVjdF90eXBlIiwgImRhdGUiLCJwYXJhbWV0ZXJfbmFtZSIsInBhcmFtZXRlcl92YWx1ZSIpCmR0MgpgYGAKCgpgYGB7cn0KcHJpbnQoZGltKGR0MikpCnNsPC1vYmplY3Quc2l6ZShkdDIpCnByaW50KHNsLCB1bml0cyA9ICJhdXRvIiwgc3RhbmRhcmQgPSAiU0kiKSAKYGBgCmBgYHtyfQpkYXRhX3Byb2Nlc3MgPC0gZHQyICU+JQogIG11dGF0ZSggZGF0ZV90cmFucz1tZHlfaG1zKGRhdGUpLCAjIG11c3QgaGF2ZSBtZHlfaG1zIGZvciBjb252ZXJ0IGRhdGUgdGltZQogICAgICAgICAgZGF0ZV9maWx0ZXI9YXNfZGF0ZShkYXRlX3RyYW5zKSwKICAgICAgICAgKQpoZWFkKGRhdGFfcHJvY2VzcykKdGFpbChkYXRhX3Byb2Nlc3MpCmBgYAoKCmBgYHtyfQpwcmludChkaW0oZGF0YV9wcm9jZXNzKSkKc2w8LW9iamVjdC5zaXplKGRhdGFfcHJvY2VzcykKcHJpbnQoc2wsIHVuaXRzID0gImF1dG8iLCBzdGFuZGFyZCA9ICJTSSIpIApgYGAKCgpgYGB7cn0KI3JtKGR0MikKYGBgCgpgYGB7cn0KbWluKGRhdGFfcHJvY2VzcyRkYXRlKQptYXgoZGF0YV9wcm9jZXNzJGRhdGUpCmBgYApgYGB7cn0KZGF0YV9wcm9jZXNzW3doaWNoLm1heChkYXRhX3Byb2Nlc3MkZGF0ZSldCmBgYApgYGB7cn0KY2xhc3MoZGF0YV9wcm9jZXNzJGRhdGVfdHJhbnMpCmNsYXNzKGRhdGFfcHJvY2VzcyRkYXRlKQptaW4oZGF0YV9wcm9jZXNzJGRhdGVfdHJhbnMpCm1heChkYXRhX3Byb2Nlc3MkZGF0ZV90cmFucykKZGltKGRhdGFfcHJvY2VzcykKYGBgCgpgYGB7cn0KI2RhdGFfcHJvY2VzcyAlPiUgCiMgIGZpbHRlcihkYXRlX3RyYW5zPj1hcy5QT1NJWGN0KCIyMDE3LTEyLTIwIDIzOjMwOjAxIix0ej0iVVRDIikpCmBgYAoKCmBgYHtyfQojcGxlYXNlIGNob29zZSBzcGVjaWZpYyB0aW1lIHRvIHNob3cKI3llYXJfc2VsZWN0PTIwMTcKI21vbnRoX3NlbGVjdD0xMgojZGF5X3NlbGVjdD0yMgojZGZfcGxvdCA8LSBkYXRhX3Byb2Nlc3MgJT4lIAojICBzZWxlY3QoZGF0ZV90cmFucyxkYXRlLHBhcmFtZXRlcl9uYW1lLHBhcmFtZXRlcl92YWx1ZSx5ZWFyLG1vbnRoLGRheSkgJT4lIAojICBmaWx0ZXIoeWVhcj09eWVhcl9zZWxlY3QsbW9udGg9PW1vbnRoX3NlbGVjdCxkYXk9PWRheV9zZWxlY3QpCiNkZl9wbG90CmBgYAoKYGBge3J9CiMgQmVzdCB0byBjaG9vc2UKZGF0ZV9jaG9vc2U9IjIwMTctMTItMTkiCmRmX3Bsb3QyIDwtIGRhdGFfcHJvY2VzcyAlPiUgCiAgc2VsZWN0KGRhdGVfdHJhbnMsZGF0ZSxkYXRlX2ZpbHRlcixwYXJhbWV0ZXJfbmFtZSxwYXJhbWV0ZXJfdmFsdWUpICU+JSAKICBmaWx0ZXIoZGF0ZV9maWx0ZXI9PXltZChkYXRlX2Nob29zZSkpCmRmX3Bsb3QyCmBgYApgYGB7cn0Kc3VtbWFyeShkZl9wbG90MikKYGBgCmBgYHtyfQojaW5zdGFsbC5wYWNrYWdlcygncGFzdGVjcycpCmxpYnJhcnkocGFzdGVjcykKc3RhdC5kZXNjKGRmX3Bsb3QyICU+JSBzZWxlY3QocGFyYW1ldGVyX25hbWUscGFyYW1ldGVyX3ZhbHVlKSkKYGBgCmBgYHtyfQojaW5zdGFsbC5wYWNrYWdlcygnSG1pc2MnKQpsaWJyYXJ5KEhtaXNjKQpkZXNjcmliZShkZl9wbG90MiAlPiUgc2VsZWN0KHBhcmFtZXRlcl9uYW1lLHBhcmFtZXRlcl92YWx1ZSkpCmBgYAoKYGBge3J9CiNpbnN0YWxsLnBhY2thZ2VzKCdwc3ljaCcpCmxpYnJhcnkocHN5Y2gpCmRlc2NyaWJlKGRmX3Bsb3QyICU+JSBzZWxlY3QocGFyYW1ldGVyX25hbWUscGFyYW1ldGVyX3ZhbHVlKSkKYGBgCmBgYHtyfQpkZl9wbG90MiAlPiUgc2VsZWN0KHBhcmFtZXRlcl92YWx1ZSkgJT4lIAogIGdncGxvdChhZXMoeT1wYXJhbWV0ZXJfdmFsdWUpKSsKICBnZW9tX2hpc3RvZ3JhbSgpCmBgYAoKCmBgYHtyfQojIGxpYnJhcnkocGxvdGx5KQojIGF5IDwtIGxpc3QoCiMgICB0aWNrZm9udCA9IGxpc3QoY29sb3IgPSAicmVkIiksCiMgICBvdmVybGF5aW5nID0gInkiLAojICAgc2lkZSA9ICJyaWdodCIsCiMgICB0aXRsZSA9ICJzZWNvbmQgeSBheGlzIgojICkKIyBwIDwtIGRmX3Bsb3QyICU+JSAKIyAgICAgICAjYXJyYW5nZShkYXRlX3RyYW5zKSAlPiUgCiMgICAgICAgcGxvdF9seSh4ID1+ZGF0ZV90cmFucywgeSA9IH5wYXJhbWV0ZXJfdmFsdWUsbmFtZT0ndmFsdWUnLAojICAgICAgICAgICAgICAgdHlwZT0nc2NhdHRlcicsbW9kZT0nbGluZXMrbWFya2VycycpJT4lIAojICAgICAgICAgICAgICAgYWRkX3RyYWNlKHg9fmRhdGVfdHJhbnMsIHkgPSB+cGFyYW1ldGVyX25hbWUsbmFtZT0nbmFtZScsCiMgICAgICAgICAgICAgICB0eXBlPSdzY2F0dGVyJyxtb2RlPSdsaW5lcycseWF4aXM9J3kyJykgJT4lIAojICAgICAgICAgICAgICAgbGF5b3V0KHlheGlzMiA9IGxpc3Qob3ZlcmxheWluZyA9ICJ5Iiwgc2lkZSA9ICJyaWdodCIpCiMgICAgICAgICAgICAgICApCiMgcApgYGAKYGBge3J9CiNwMTwtcGxvdF9seShkZl9wbG90Mix4ID1+ZGF0ZV90cmFucywgeSA9IH5wYXJhbWV0ZXJfdmFsdWUpICU+JSAKIyAgYWRkX2xpbmVzKG5hbWU9J1ZhbHVlJykgJT4lIAojcDI8LXBsb3RfbHkoZGZfcGxvdDIseCA9fmRhdGVfdHJhbnMsIHkgPSB+cGFyYW1ldGVyX25hbWUpICU+JSAKIyAgYWRkX2xpbmVzKG5hbWU9J0ZyZXF1ZW5jeScpCiNzdWJwbG90KHAxLCBwMixucm93cz0yLHNoYXJlWCA9IFRSVUUpCmBgYAoKYGBge3J9CmxpYnJhcnkocGxvdGx5KQpwMTwtcGxvdF9seShkZl9wbG90Mix4ID1+ZGF0ZV90cmFucywgeSA9IH5wYXJhbWV0ZXJfdmFsdWUpICU+JSAKICBhZGRfdHJhY2UobW9kZT0nbGluZXMrbWFya2VycycsbmFtZT0nVmFsdWUnKQpwMjwtcGxvdF9seShkZl9wbG90Mix4ID1+ZGF0ZV90cmFucywgeSA9IH5wYXJhbWV0ZXJfbmFtZSkgJT4lIAogIGFkZF90cmFjZShtb2RlPSdsaW5lcyttYXJrZXJzJyxuYW1lPSdGcmVxdWVuY3knKQoKcGxvdGx5OjpzdWJwbG90KHAxLCBwMixucm93cz0yLHNoYXJlWCA9IFRSVUUpCgpgYGAKCmBgYHtyfQpzZWxlY3RfZGF0YTwtZGZfcGxvdDIkcGFyYW1ldGVyX3ZhbHVlClExIDwtIHF1YW50aWxlKHNlbGVjdF9kYXRhLCAuMjUpClEzIDwtIHF1YW50aWxlKHNlbGVjdF9kYXRhLCAuNzUpCklRUiA8LSBJUVIoc2VsZWN0X2RhdGEpCms9MwpkZl9wbG90X25vX291dGxpZXIgPC0gc3Vic2V0KGRmX3Bsb3QyLCBzZWxlY3RfZGF0YT4gKFExIC0gaypJUVIpICYgc2VsZWN0X2RhdGE8IChRMyArIGsqSVFSKSkKCnByaW50KGRpbShkZl9wbG90MikpCnByaW50KGRpbShkZl9wbG90X25vX291dGxpZXIpKQpgYGAKYGBge3J9CnAxPC1wbG90X2x5KGRmX3Bsb3Rfbm9fb3V0bGllcix4ID1+ZGF0ZV90cmFucywgeSA9IH5wYXJhbWV0ZXJfdmFsdWUpICU+JSAKICBhZGRfdHJhY2UobW9kZT0nbGluZXMrbWFya2VycycsbmFtZT0nVmFsdWUnKQpwMjwtcGxvdF9seShkZl9wbG90X25vX291dGxpZXIseCA9fmRhdGVfdHJhbnMsIHkgPSB+cGFyYW1ldGVyX25hbWUpICU+JSAKICBhZGRfdHJhY2UobW9kZT0nbGluZXMrbWFya2VycycsbmFtZT0nRnJlcXVlbmN5JykKcDwtcGxvdGx5OjpzdWJwbG90KHAxLCBwMixucm93cz0yLHNoYXJlWCA9IFRSVUUpCnAKYGBgCmBgYHtyfQpwMTwtcGxvdF9seShkZl9wbG90X25vX291dGxpZXIseCA9fmRhdGVfdHJhbnMsIHkgPSB+cGFyYW1ldGVyX3ZhbHVlKSAlPiUgCiAgYWRkX3RyYWNlKG1vZGU9J2xpbmVzK21hcmtlcnMnLG5hbWU9J1ZhbHVlJykKI3AyPC1wbG90X2x5KGRmX3Bsb3Rfbm9fb3V0bGllcix4ID1+ZGF0ZV90cmFucywgeSA9IH5wYXJhbWV0ZXJfbmFtZSkgJT4lIAojICBhZGRfdHJhY2UobW9kZT0nbGluZXMrbWFya2VycycsbmFtZT0nRnJlcXVlbmN5JykKI3A8LXN1YnBsb3QocDEsIHAyLG5yb3dzPTIsc2hhcmVYID0gVFJVRSkKcDEKYGBgCmBgYHtyfQpwMTwtcGxvdF9seShkZl9wbG90X25vX291dGxpZXIseCA9fmRhdGVfdHJhbnMsIHkgPSB+cGFyYW1ldGVyX3ZhbHVlKSAlPiUgCiAgYWRkX3RyYWNlKG1vZGU9J2xpbmVzK21hcmtlcnMnLG5hbWU9J1ZhbHVlJykgJT4lIAogIGxheW91dCgKICAgIHRpdGxlID0gIkZRQyBkYXRhIGRhaWx5IiwKICAgIHhheGlzID0gbGlzdCgKICAgICAgcmFuZ2VzZWxlY3RvciA9IGxpc3QoCiAgICAgICAgYnV0dG9ucyA9IGxpc3QoCiAgICAgICAgICBsaXN0KAogICAgICAgICAgICBjb3VudCA9IDMwLAogICAgICAgICAgICBsYWJlbCA9ICJtaW4iLAogICAgICAgICAgICBzdGVwID0gIm1pbnV0ZSIsCiAgICAgICAgICAgIHN0ZXBtb2RlID0gImJhY2t3YXJkIiksCiAgICAgICAgICBsaXN0KAogICAgICAgICAgICBjb3VudCA9IDIsCiAgICAgICAgICAgIGxhYmVsID0gImhvdXIiLAogICAgICAgICAgICBzdGVwID0gImhvdXIiLAogICAgICAgICAgICBzdGVwbW9kZSA9ICJiYWNrd2FyZCIpLAogICAgICAgICAgbGlzdChzdGVwID0gImFsbCIpKSksCgogICAgICByYW5nZXNsaWRlciA9IGxpc3QodHlwZSA9ICJkYXRlIikpLAoKICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICJWYWx1ZSIpKQpwMQpgYGAKCgpgYGB7cn0KIyBheSA8LSBsaXN0KAojICAgdGlja2ZvbnQgPSBsaXN0KGNvbG9yID0gInJlZCIpLAojICAgb3ZlcmxheWluZyA9ICJ5IiwKIyAgIHNpZGUgPSAicmlnaHQiLAojICAgdGl0bGUgPSAic2Vjb25kIHkgYXhpcyIKIyApCiMgcCA8LSBkZl9wbG90X25vX291dGxpZXIgJT4lIAojICAgICAgIGFycmFuZ2UoZGF0ZV90cmFucykgJT4lIAojICAgICAgIHBsb3RfbHkoeCA9fmRhdGVfdHJhbnMsIHkgPSB+cGFyYW1ldGVyX3ZhbHVlLG5hbWU9J3ZhbHVlJywKIyAgICAgICAgICAgICAgIHR5cGU9J3NjYXR0ZXInLG1vZGU9J2xpbmVzK21hcmtlcnMnKSU+JSAKIyAgICAgICAgICAgICAgIGFkZF90cmFjZSh4PX5kYXRlX3RyYW5zLCB5ID0gfnBhcmFtZXRlcl9uYW1lLG5hbWU9J25hbWUnLAojICAgICAgICAgICAgICAgdHlwZT0nc2NhdHRlcicsbW9kZT0nbGluZXMnLHlheGlzPSd5MicpICU+JSAKIyAgICAgICAgICAgICAgIGxheW91dCh5YXhpczIgPSBsaXN0KG92ZXJsYXlpbmcgPSAieSIsIHNpZGUgPSAicmlnaHQiKQojICAgICAgICAgICAgICAgKQojIHAKYGBgCgpgYGB7cn0KbnVtX3BvaW50cz1kaW0oZGZfcGxvdF9ub19vdXRsaWVyKVsxXQpudW1fcG9pbnRzCmBgYAoKYGBge3J9ClVTTF92YWx1ZT0nJwpMU0xfdmFsdWU9JycKTFNMPC1yZXAoTFNMX3ZhbHVlLG51bV9wb2ludHMpClVTTDwtcmVwKFVTTF92YWx1ZSxudW1fcG9pbnRzKQpwMSU+JSAKICBhZGRfdHJhY2UoeSA9IH5VU0wsIG5hbWUgPSAnVVNMJywgbW9kZSA9ICdsaW5lcycsY29sb3I9InJnYmEoMjU1LCAwLCAwLCAwLjYpIikgJT4lIAogIGFkZF90cmFjZSh5ID0gfkxTTCwgbmFtZSA9ICdMU0wnLCBtb2RlID0gJ2xpbmVzJyxjb2xvcj0icmdiKDIwLCAyMCwgMjApIikKYGBgClRyeSBhbm90aGVyIGNoYXJ0OgpIaWdoIGNoYXJ0CmBgYHtyfQpoZWFkKGRmX3Bsb3Rfbm9fb3V0bGllcikKYGBgCgpUUlkgT1RIRVIgTUVUSE9EOgpgYGB7cn0KI2luc3RhbGwucGFja2FnZXMoJ2hpZ2hjaGFydGVyJykKbGlicmFyeShoaWdoY2hhcnRlcikKYGBgCgpgYGB7cn0KZHQyJT4lCiAgaGNoYXJ0KHR5cGUgPSAibGluZSIsIGhjYWVzKHggPSBWNiwgeSA9IFY2NikpCmBgYAoKYGBge3J9CmRmX3Bsb3Rfbm9fb3V0bGllciU+JQogIGhjaGFydCh0eXBlID0gImxpbmUiLCBoY2Flcyh4ID0gYXMuY2hhcmFjdGVyKGRhdGVfdHJhbnMpLCB5ID0gcGFyYW1ldGVyX3ZhbHVlKSkKYGBgCmBgYHtyfQojaW5zdGFsbC5wYWNrYWdlcygiZHlncmFwaHMiKQpsaWJyYXJ5KGR5Z3JhcGhzKQpkZl9wbG90X25vX291dGxpZXIKZHQyCmBgYApgYGB7cn0KU3lzLnRpbWV6b25lKCkKdHpvbmUoZGF0YV90aW1lJGRhdGVfdHJhbnMpCnR6b25lKGRmX3Bsb3Rfbm9fb3V0bGllciRkYXRlX3RyYW5zKQpgYGAKCmBgYHtyfQpzdHIoZHQyJFY2KQpzdHIoZGZfcGxvdF9ub19vdXRsaWVyJGRhdGVfdHJhbnMpCnN0cihhcy5EYXRlKGRmX3Bsb3Rfbm9fb3V0bGllciRkYXRlX3RyYW5zLGZvcm1hdD0nJVktJW0tJWQgJUg6JU06JVMnKSkKYGBgCgpgYGB7cn0KIyBTd2l0Y2ggdG8gWFRTIGZvcm1hdApkYXRhIDwtIHh0cyh4ID0gZHQyJFY2NiwgCiAgICAgICAgICAgIG9yZGVyLmJ5ID0gbWR5X2htcyhkdDIkVjYpKQojIEFkZCBwb2ludHMKcGxvdF9keWdyYXBoIDwtIGR5Z3JhcGgoZGF0YSkgJT4lCiAgZHlPcHRpb25zKCBkcmF3UG9pbnRzID0gVFJVRSwgcG9pbnRTaXplID0gNCx1c2VEYXRhVGltZXpvbmUgPSBUUlVFICklPiUgCiAgZHlSYW5nZVNlbGVjdG9yKCkKcGxvdF9keWdyYXBoCmBgYAoKCmBgYHtyfQojIFN3aXRjaCB0byBYVFMgZm9ybWF0CmRhdGEgPC0geHRzKHggPSBkZl9wbG90X25vX291dGxpZXIkcGFyYW1ldGVyX3ZhbHVlLCAKICAgICAgICAgICAgb3JkZXIuYnkgPSBkZl9wbG90X25vX291dGxpZXIkZGF0ZV90cmFucykKIyBBZGQgcG9pbnRzCnAgPC0gZHlncmFwaChkYXRhKSAlPiUKICBkeU9wdGlvbnMoIGRyYXdQb2ludHMgPSBUUlVFLCBwb2ludFNpemUgPSA0LHVzZURhdGFUaW1lem9uZSA9IFRSVUUgKSU+JSAKICBkeVJhbmdlU2VsZWN0b3IoKQpwCmBgYApgYGB7cn0KZGZfcGxvdF9ub19vdXRsaWVyCmBgYAoKYGBge3J9CmR5Z3JhcGgoZGZfcGxvdF9ub19vdXRsaWVyICU+JSBzZWxlY3QoZGF0ZV90cmFucyxwYXJhbWV0ZXJfdmFsdWUpLCBtYWluID0gIkFsbCIsIGdyb3VwID0gImx1bmctZGVhdGhzIiklPiUKICBkeU9wdGlvbnMoIGRyYXdQb2ludHMgPSBUUlVFLCBwb2ludFNpemUgPSA0LHVzZURhdGFUaW1lem9uZSA9IFRSVUUgKQpkeWdyYXBoKGRmX3Bsb3Rfbm9fb3V0bGllciAlPiUgc2VsZWN0KGRhdGVfdHJhbnMscGFyYW1ldGVyX25hbWUpLCBtYWluID0gIkFsbCIsIGdyb3VwID0gImx1bmctZGVhdGhzIiklPiUKICBkeU9wdGlvbnMoIGRyYXdQb2ludHMgPSBUUlVFLCBwb2ludFNpemUgPSA0LHVzZURhdGFUaW1lem9uZSA9IFRSVUUgKQpgYGAKYGBge3J9CmR5X2dyYXBoIDwtIGxpc3QoCiAgZHlncmFwaChkZl9wbG90X25vX291dGxpZXIgJT4lIHNlbGVjdChkYXRlX3RyYW5zLHBhcmFtZXRlcl92YWx1ZSksIG1haW4gPSAiZGIiLCBncm91cCA9ICJsdW5nLWRlYXRocyIpJT4lCiAgZHlPcHRpb25zKCBkcmF3UG9pbnRzID0gVFJVRSwgcG9pbnRTaXplID0gNCx1c2VEYXRhVGltZXpvbmUgPSBUUlVFICksCmR5Z3JhcGgoZGZfcGxvdF9ub19vdXRsaWVyICU+JSBzZWxlY3QoZGF0ZV90cmFucyxwYXJhbWV0ZXJfbmFtZSksIG1haW4gPSAiRnJlcXVlbmN5IiwgZ3JvdXAgPSAibHVuZy1kZWF0aHMiKSU+JQogIGR5T3B0aW9ucyggZHJhd1BvaW50cyA9IFRSVUUsIHBvaW50U2l6ZSA9IDQsdXNlRGF0YVRpbWV6b25lID0gVFJVRSApCikgICMgZW5kIGxpc3QKCiMgcmVuZGVyIHRoZSBkeWdyYXBocyBvYmplY3RzIHVzaW5nIGh0bWx0b29scwpodG1sdG9vbHM6OmJyb3dzYWJsZShodG1sdG9vbHM6OnRhZ0xpc3QoZHlfZ3JhcGgpKQpgYGAKCgoKYGBge3J9CmBgYAoKCmBgYHtyfQpgYGAKCgpgYGB7cn0KIyBQbGVhc2UgY2hvb3NlIHByb2R1Y3RfdHlwZToKZmlsZT0nL21lZGlhL2FkLzAxRDZCNTdDRkJFNERCMjAvMS5MaW51eC9EYXRhL0ZRQy9WMDRSLVYwNFItU1FMRGF0YV8zMDAwX2hlYWQuZGF0JyAKI3Byb2R1Y3RfdHlwZT0nMzFBQTAxNScKcHJvZHVjdF90eXBlX2Nob29zZT0nMzFBQTAxNScKI3Byb2R1Y3RfdHlwZT0nMzFBMDA3R19QJwojIFBsZWFzZSBjaG9vc2UgcGFyYW1ldGVyIGNvbHVtbiB0byBzaG93CnBhcmFtZXRlcl9jb2x1bW5fbmFtZT0nVjY1JwpwYXJhbWV0ZXJfY29sdW1uX3ZhbHVlPSdWNjYnCiMgRGVmYXVsdCB0aW1lIGNvbHVtbjoKcHJvZHVjdF90eXBlX2NvbHVtbj0nVjMnCmRhdGVfY29sdW1uPSdWNicKCnNhdmVmdW5jMiA8LSBmdW5jdGlvbihmaWxlX3BhdGgscHJvZHVjdF90eXBlX2NvbHVtbixwcm9kdWN0X3R5cGVfY2hvb3NlPU5VTEwsZGF0ZV9jb2x1bW49TlVMTCwKICAgICAgICAgICAgICAgICAgICAgICAgcGFyYW1ldGVyX2NvbHVtbl9uYW1lPU5VTEwscGFyYW1ldGVyX2NvbHVtbl92YWx1ZT1OVUxMKXsKICAgIHRyeUNhdGNoKAogICAgICBleHByICAgID0gewogICAgICAgIGlmICggaXMubnVsbChwcm9kdWN0X3R5cGVfY2hvb3NlKSl7CiAgICAgICAgICBwcmludCgnbm90IGZpbHRlcicpCiAgICAgICAgICBkdDIgPDwtIGZyZWFkKGZpbGVfcGF0aCxmaWxsPVRSVUUsc2VsZWN0PWMocHJvZHVjdF90eXBlX2NvbHVtbixkYXRlX2NvbHVtbixwYXJhbWV0ZXJfY29sdW1uX25hbWUscGFyYW1ldGVyX2NvbHVtbl92YWx1ZSkpfQogICAgICAgIGVsc2V7CiAgICAgICAgICBwcmludCgnZmlsdGVyJykKICAgICAgICAgIGR0MiA8PC0gZnJlYWQoZmlsZV9wYXRoLGZpbGw9VFJVRSxzZWxlY3Q9Yyhwcm9kdWN0X3R5cGVfY29sdW1uLGRhdGVfY29sdW1uLHBhcmFtZXRlcl9jb2x1bW5fbmFtZSxwYXJhbWV0ZXJfY29sdW1uX3ZhbHVlKSkgJT4lCiAgICAgICAgICBmaWx0ZXIoVjMgPT1wcm9kdWN0X3R5cGVfY2hvb3NlKX0KICAgICAgICAKICAgICAgfSwKICAgICAgd2FybmluZyA9IGZ1bmN0aW9uKHcpewogICAgICAgIGNhdCgnV2FybmluZzogJywgdyRtZXNzYWdlLCAnXG5cbicpOwogICAgICAgIG5fbGluZTIgPC0gYXMubnVtZXJpYyhnc3ViKCdTdG9wcGVkIGVhcmx5IG9uIGxpbmUgKFxcZCspXFwuLionLCdcXDEnLHckbWVzc2FnZSkpCiAgICAgICAgaWYgKCFpcy5uYShuX2xpbmUyKSkgewogICAgICAgICAgY2F0KCdGb3VuZCAnLCBuX2xpbmUyLCdcbicpCiAgICAgICAgICBkdDJfcGFydDEgPC0gZnJlYWQoZmlsZV9wYXRoLGZpbGw9VFJVRSwgbnJvd3M9bl9saW5lMi0xLHNlbGVjdD1jKHByb2R1Y3RfdHlwZV9jb2x1bW4sZGF0ZV9jb2x1bW4scGFyYW1ldGVyX2NvbHVtbl9uYW1lLHBhcmFtZXRlcl9jb2x1bW5fdmFsdWUpKQogICAgICAgICAgZHQyX3BhcnQyIDwtIGZyZWFkKGZpbGVfcGF0aCxmaWxsPVRSVUUsc2tpcD1uX2xpbmUyLHNlbGVjdD1jKHByb2R1Y3RfdHlwZV9jb2x1bW4sZGF0ZV9jb2x1bW4scGFyYW1ldGVyX2NvbHVtbl9uYW1lLHBhcmFtZXRlcl9jb2x1bW5fdmFsdWUpKQogICAgICAgICAgaWYgKCBpcy5udWxsKHByb2R1Y3RfdHlwZV9jaG9vc2UpKXsKICAgICAgICAgICAgZHQyIDw8LSByYmluZChkdDJfcGFydDEsIGR0Ml9wYXJ0MiwgZmlsbD1UKQogICAgICAgICAgfWVsc2V7CiAgICAgICAgICAgIGR0MiA8PC0gcmJpbmQoZHQyX3BhcnQxLCBkdDJfcGFydDIsIGZpbGw9VCklPiUKICAgICAgICAgICAgICBmaWx0ZXIoVjMgPT1wcm9kdWN0X3R5cGVfY2hvb3NlKSAgCiAgICAgICAgICB9CiAgICAgICAgICAKICAgICAgICB9CiAgICAgIH0sCiAgICAgIGZpbmFsbHkgPSBjYXQoIlxuRmluaXNoZWQuIFxuIikKICAgICk7Cn0KCgpkdDwtc2F2ZWZ1bmMyKGZpbGUscHJvZHVjdF90eXBlX2NvbHVtbixwcm9kdWN0X3R5cGVfY2hvb3NlLGRhdGVfY29sdW1uLHBhcmFtZXRlcl9jb2x1bW5fbmFtZSxwYXJhbWV0ZXJfY29sdW1uX3ZhbHVlKQpjb2xuYW1lcyhkdCkgPC0gYygicHJvZHVjdF90eXBlIiwgImRhdGUiLCJwYXJhbWV0ZXJfZnJlcSIsInBhcmFtZXRlcl92YWx1ZSIpCmR0PC1kdCAlPiUKICBtdXRhdGUoIGRhdGVfdHJhbnM9bWR5X2htcyhkYXRlKSwgIyBtdXN0IGhhdmUgbWR5X2htcyBmb3IgY29udmVydCBkYXRlIHRpbWUKICAgICAgICAgIGRhdGVfZmlsdGVyPWFzX2RhdGUoZGF0ZV90cmFucyksCiAgICAgICAgICApCmR0CmBgYAoKCgpgYGB7cn0KZHQ8LXNhdmVmdW5jMihmaWxlLHByb2R1Y3RfdHlwZV9jb2x1bW4pCmR0CmBgYAoKCmBgYHtyfQpwbG90bHlfY2hhcnQgPC0gZnVuY3Rpb24oZGF0YV9vbmVfZGF0ZSxjaGVja19pbnB1dF9yZW1vdmVfZnJlcXVlbmN5X2NoYXJ0LAogICAgICAgICAgICAgICAgICAgICAgICAgY2hlY2tfZ29fZGF0YV9hbmFseXplX2RhdGUpewogIHJlcShjaGVja19nb19kYXRhX2FuYWx5emVfZGF0ZSkKICBwMTwtcGxvdF9seShkYXRhX29uZV9kYXRlLHggPX5kYXRlX3RyYW5zLCB5ID0gfnBhcmFtZXRlcl92YWx1ZSkgJT4lCiAgICAgIGFkZF90cmFjZShtb2RlPSdsaW5lcyttYXJrZXJzJyxuYW1lPSdWYWx1ZScpCiAgICBpZiAoY2hlY2tfaW5wdXRfcmVtb3ZlX2ZyZXF1ZW5jeV9jaGFydCl7CiAgICAgIHAxCiAgICB9IGVsc2UgewogICAgICBwMjwtcGxvdF9seShkYXRhX29uZV9kYXRlLHggPX5kYXRlX3RyYW5zLCB5ID0gfnBhcmFtZXRlcl9mcmVxKSAlPiUKICAgICAgICBhZGRfdHJhY2UobW9kZT0nbGluZXMrbWFya2VycycsbmFtZT0nRnJlcXVlbmN5JykKICAgICAgcGxvdGx5OjpzdWJwbG90KHAxLCBwMixucm93cz0yLHNoYXJlWCA9IFRSVUUpCiAgICAgIAogICAgfQp9CnBsb3RseV9jaGFydChkYXRhX29uZV9kYXRlKCksaW5wdXQkcmVtb3ZlX2ZyZXF1ZW5jeV9jaGFydCxpbnB1dCRnb19kYXRhX2FuYWx5emVfZGF0ZSkKYGBgCgoKYGBge3J9CmBgYAoK